package utils

import (
	"bytes"
	_ "embed"
	"errors"
	"fmt"
	"github.com/go-logr/logr"
	"github.com/lecang-installer/api/v1beta1"
	"github.com/lecang-installer/internal/files"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	storagev1 "k8s.io/api/storage/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/util/yaml"
	"strings"
	"text/template"
)

type Config struct {
	// 'redis:6.2.4'
	Name                string
	Image               string
	InitImage           string
	Namespace           string
	Port                int
	NodePort            int
	HttpPort            int
	HttpNodePort        int
	Env                 []corev1.EnvVar
	ResourceLimit       corev1.ResourceRequirements
	ConfigmapName       string
	ConfigmapData       map[string]string
	PvcStorageClassName string
	PvStorageClassName  string
	PvcName             string
	PvName              string
	NfsServer           string
	NfsPath             string
	StorageClassName    string
	StorageSize         string
	PvLocalPath         string
	PvNodeName          string
}

var (
	level1ContainerEnv = []corev1.EnvVar{
		{
			Name:  "PROFILE",
			Value: "dev,k8s",
		},
		{
			Name:  "JAVA_OPTS",
			Value: "-Xss8m -Xmx10444m -Xms9399m -XX:MaxMetaspaceSize=4g\n -XX:MetaspaceSize=2g -XX:+UseParallelGC -XX:+UseParallelOldGC",
		},
	}

	level2ContainerEnv = []corev1.EnvVar{
		{
			Name:  "PROFILE",
			Value: "dev,k8s",
		},
		{
			Name:  "JAVA_OPTS",
			Value: "-Xss8m -Xmx8192m -Xms6144m -XX:MaxMetaspaceSize=4g\n -XX:MetaspaceSize=2g -XX:+UseParallelGC -XX:+UseParallelOldGC",
		},
	}
	level3ContainerEnv = []corev1.EnvVar{
		{
			Name:  "PROFILE",
			Value: "dev,k8s",
		},
		{
			Name:  "JAVA_OPTS",
			Value: "-Xss8m -Xmx4096m -Xms2048m -XX:MaxMetaspaceSize=512m\n -XX:MetaspaceSize=256m -XX:+UseParallelGC -XX:+UseParallelOldGC",
		},
	}
	level1ResourceLimit = corev1.ResourceRequirements{
		Limits: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("12Gi"),
			corev1.ResourceCPU:    resource.MustParse("4"),
		},
		Requests: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("12Gi"),
			corev1.ResourceCPU:    resource.MustParse("4"),
		},
	}
	level2ResourceLimit = corev1.ResourceRequirements{
		Limits: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("8Gi"),
			corev1.ResourceCPU:    resource.MustParse("4"),
		},
		Requests: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("4Gi"),
			corev1.ResourceCPU:    resource.MustParse("2"),
		},
	}
	level3ResourceLimit = corev1.ResourceRequirements{
		Limits: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("4Gi"),
			corev1.ResourceCPU:    resource.MustParse("2"),
		},
		Requests: corev1.ResourceList{
			corev1.ResourceMemory: resource.MustParse("2Gi"),
			corev1.ResourceCPU:    resource.MustParse("1"),
		},
	}
	testResourceLimit = corev1.ResourceRequirements{}

	configmap = []corev1.VolumeMount{
		{
			MountPath: "/app/application.yml",
			SubPath:   "application.yml",
		},
	}

	Pvc corev1.PersistentVolumeClaim

	appsPort = 80
)

func TemplateNfsParseClusterRole(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		Name: resName,
	}
	return TemplateParseHandle(files.NfsClusterRoleYaml, config, resName, logger)

}

func TemplateParseNfsClusterRoleBinding(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		Name: resName,
	}
	return TemplateParseHandle(files.NfsClusterRoleBindingYaml, config, resName, logger)
}

func TemplateParseNfsDeployment(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		Name:      resName,
		NfsServer: installer.Spec.NfsProvisioner.NfsServer,
		NfsPath:   installer.Spec.NfsProvisioner.NfsPath,
	}
	return TemplateParseHandle(files.NfsDeploymentYaml, config, resName, logger)
}

func TemplateParseNfsPvc(resName, storageClassName, PvcName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		PvcName:             PvcName,
		Namespace:           installer.Namespace,
		PvcStorageClassName: storageClassName,
		StorageSize:         installer.Spec.NfsProvisioner.StorageSize,
	}
	return TemplateParseHandle(files.NfsPvcYaml, config, resName, logger)
}

func TemplateParseNfsRoleLeader(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{}
	return TemplateParseHandle(files.NfsRoleLeaderYaml, config, resName, logger)
}

func TemplateParseNfsRoleBindingLeader(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{}
	return TemplateParseHandle(files.NfsRoleBindingLeaderYaml, config, resName, logger)
}

func TemplateParseNfsServiceAccount(resName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{}
	return TemplateParseHandle(files.NfsSaYaml, config, resName, logger)
}

func TemplateParseNfsStorageClass(resName, storageClassName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		StorageClassName: storageClassName,
	}
	return TemplateParseHandle(files.NfsStorageClassYaml, config, resName, logger)
}

func NewDeploy(installer *v1beta1.Installer, logger logr.Logger) (resources []interface{}, err error) {

	for k, v := range installer.Spec.Middlewares {
		// check resource limit
		var middleLimitLevel corev1.ResourceRequirements
		switch v.LimitLevel {
		case 0:
			middleLimitLevel = testResourceLimit
		case 1:
			middleLimitLevel = level1ResourceLimit
		case 2:
			middleLimitLevel = level2ResourceLimit
		case 3:
			middleLimitLevel = level3ResourceLimit
		}

		config := Config{
			Name:         v.Name,
			Image:        v.Image,
			Namespace:    installer.Namespace,
			Port:         v.Port,
			NodePort:     v.NodePort,
			HttpPort:     v.HttpPort,
			HttpNodePort: v.HttpNodePort,
		}

		dep, svc, err := handleMiddlewares(config, k, v, logger, middleLimitLevel)
		if err != nil {
			logger.WithName("Operator HandleMiddleware "+k).Error(err, "HandleMiddleware error...")
			continue
		}

		//switch k {
		//case "redis":
		//	logger.WithName("Installer NewDeploy").Info("Handle Deployment Redis...")
		//	// 定义变量
		//	config := Config{
		//		Name:         v.Name,
		//		Image:        v.Image,
		//		Namespace:    installer.Namespace,
		//		Port:         v.Port,
		//		NodePort:     v.NodePort,
		//		HttpPort:     v.HttpPort,
		//		HttpNodePort: v.HttpNodePort,
		//	}
		//
		//	// 解析模板
		//	//depTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/redis.yaml")
		//
		//	// Template Parse and Rendered Deployment YAML file
		//	depBytes, err := TemplateParseHandle(files.RedisYaml, config, k, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Deployment YAML file failed")
		//		return nil, err
		//	}
		//	logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(" Template Execute Deployment YAML file success")
		//
		//	dep := &appsv1.Deployment{}
		//	depObj, err := yamlUnmarshalHandle(depBytes, dep, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
		//		return nil, err
		//	}
		//	dep = depObj.(*appsv1.Deployment)
		//	dep.Spec.Template.Spec.Containers[0].Resources = middleLimitLevel
		//
		//	//tmpl, err := template.New("yaml").Parse("/data/operator/installer/internal/files/redis.yaml")
		//	//logger.WithName("Installer NewDeploy").Info("Handle template YAML file...")
		//	//depTmpl, err := template.New("yaml").Parse(string(files.RedisYaml))
		//	//if err != nil {
		//	//	logger.WithName("Installer NewDeploy").Error(err, "Template parse Redis YAML file success")
		//	//	return nil, err
		//	//}
		//	//logger.WithName("Installer NewDeploy").Info("Template parse Redis YAML file success")
		//	//// 将变量注入模板并渲染
		//	//depbuf := new(bytes.Buffer)
		//	//err = depTmpl.Execute(depbuf, config)
		//	//depBytes := depbuf.Bytes()
		//
		//	if v.EnableService {
		//		// Template Parse and rendered Service YAML file
		//		svcBytes, err := TemplateParseHandle(files.ServiceYaml, config, k, logger)
		//		if err != nil {
		//			logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
		//			return nil, err
		//		}
		//		logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")
		//
		//		svc := &corev1.Service{}
		//		svcObj, err := yamlUnmarshalHandle(svcBytes, svc, logger)
		//		if err != nil {
		//			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
		//			return nil, err
		//		}
		//		svc = svcObj.(*corev1.Service)
		//
		//		logger.WithName("Installer NewDeploy").Info("Unmarshal Redis and Service YAML to Resource Type success")
		//		if v.EnableHttpPort {
		//			logger.WithName("Installer NewDeploy").Info("Redis Service enabled http Port")
		//			httpPort := corev1.ServicePort{
		//				Name:     "http",
		//				Protocol: corev1.ProtocolTCP,
		//				Port:     int32(v.HttpPort),
		//				TargetPort: intstr.IntOrString{
		//					IntVal: int32(v.HttpPort),
		//				},
		//				NodePort: int32(v.HttpNodePort),
		//			}
		//			svc.Spec.Ports = append(svc.Spec.Ports, httpPort)
		//		}
		//		resources = append(resources, svc)
		//	}
		//	//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")
		//	//svcTmpl, err := template.New("yaml").Parse(string(files.ServiceYaml))
		//	//if err != nil {
		//	//	logger.WithName("Installer NewDeploy").Error(err, "Template parse Redis Service YAML file success")
		//	//	return nil, err
		//	//}
		//	//logger.WithName("Installer NewDeploy").Info("Template parse Redis Service YAML file success")
		//
		//	// 将变量注入模板并渲染
		//	//svcbuf := new(bytes.Buffer)
		//	//err = svcTmpl.Execute(svcbuf, config)
		//	//svcBytes := svcbuf.Bytes()
		//	////err = tmpl.Execute(os.Stdout, config)
		//	//if err != nil {
		//	//	logger.WithName("Installer NewDeploy").Error(err, "Template Execute Redis Service YAML file failed")
		//	//	return nil, err
		//	//}
		//	//logger.WithName("Installer NewDeploy").Info("Template Execute Redis Service YAML file success")
		//
		//	//dep := &appsv1.Deployment{}
		//	//err = yaml.Unmarshal(depBytes, dep)
		//	//if err != nil {
		//	//	panic(err)
		//	//}
		//
		//	//svc := &corev1.Service{}
		//	//err = yaml.Unmarshal(svcBytes, svc)
		//	//if err != nil {
		//	//	panic(err)
		//	//}
		//
		//	resources = append(resources, dep)
		//
		//case "rabbitmq":
		//	logger.WithName("Installer NewDeploy").Info("Handle Deployment Rabbitmq...")
		//	// 定义变量
		//	config := Config{
		//		Name:         v.Name,
		//		Image:        v.Image,
		//		Namespace:    installer.Namespace,
		//		Port:         v.Port,
		//		NodePort:     v.NodePort,
		//		HttpPort:     v.HttpPort,
		//		HttpNodePort: v.HttpNodePort,
		//	}
		//
		//	// 解析模板
		//	//depTmpl, err := template.ParseFiles("internal/files/rabbitmq.yaml")
		//	logger.WithName("Installer NewDeploy").Info("template parse Yaml Rabbitmq...")
		//
		//	// Template Parse and rendered Deployment YAML file
		//	depBytes, err := TemplateParseHandle(files.RabbitmqYaml, config, k, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Deployment YAML file failed")
		//		return nil, err
		//	}
		//	logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(" Template Execute Deployment YAML file success")
		//
		//	dep := &appsv1.Deployment{}
		//	depObj, err := yamlUnmarshalHandle(depBytes, dep, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
		//		return nil, err
		//	}
		//	dep = depObj.(*appsv1.Deployment)
		//	dep.Spec.Template.Spec.Containers[0].Resources = middleLimitLevel
		//
		//	//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")
		//
		//	// Template Parse and rendered Service YAML file
		//	svcBytes, err := TemplateParseHandle(files.ServiceYaml, config, k, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
		//		return nil, err
		//	}
		//	logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")
		//
		//	svc := &corev1.Service{}
		//	svcObj, err := yamlUnmarshalHandle(svcBytes, svc, logger)
		//	if err != nil {
		//		logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
		//		return nil, err
		//	}
		//	svc = svcObj.(*corev1.Service)
		//
		//	logger.WithName("Installer NewDeploy " + k).Info("Unmarshal Deployment and Service Yaml to Resource Type success")
		//	if v.EnableHttpPort {
		//		logger.WithName("Installer NewDeploy " + k).Info("Service enabled http Port")
		//		svc.Spec.Type = "NodePort"
		//		httpPort := corev1.ServicePort{
		//			Name:     "http",
		//			Protocol: corev1.ProtocolTCP,
		//			Port:     int32(v.HttpPort),
		//			TargetPort: intstr.IntOrString{
		//				IntVal: int32(v.HttpPort),
		//			},
		//			NodePort: int32(v.HttpNodePort),
		//		}
		//		svc.Spec.Ports = append(svc.Spec.Ports, httpPort)
		//	}
		//	resources = append(resources, dep, svc)
		//}

		resources = append(resources, dep, svc)
	}

	for k, v := range installer.Spec.LecangApps {

		// check resource limit
		var resourceLimitLevel corev1.ResourceRequirements
		switch v.LimitLevel {
		case 0:
			resourceLimitLevel = testResourceLimit
		case 1:
			resourceLimitLevel = level1ResourceLimit
		case 2:
			resourceLimitLevel = level2ResourceLimit
		case 3:
			resourceLimitLevel = level3ResourceLimit
		}

		switch k {
		case "agentparser-java":
			logger.WithName("Installer NewDeploy " + k).Info("Handle Deployment " + k)
			// 定义变量
			config := Config{
				Name:          k,
				Image:         v.Image,
				InitImage:     installer.Spec.InitImage,
				Port:          appsPort,
				Namespace:     installer.Namespace,
				ConfigmapName: k,
			}
			// 解析模板
			//depTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/redis.yaml")
			//tmpl, err := template.New("yaml").Parse("/data/operator/installer/internal/files/redis.yaml")

			logger.WithName("Installer NewDeploy " + k).Info("Handle template YAML file " + k)

			// Template Parse and rendered Deployment YAML file
			depBytes, err := TemplateParseHandle(files.AppsYaml, config, k, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
				return nil, err
			}
			logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

			//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")

			// Template Parse and rendered Service YAML file
			svcBytes, err := TemplateParseHandle(files.AppServiceYaml, config, k, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
				return nil, err
			}
			logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

			// Unmarshal Deployment Bytes to appsv1.Deployment type
			dep := &appsv1.Deployment{}
			//err = yaml.Unmarshal(depBytes, dep)
			//if err != nil {
			//	logger.WithName("Installer NewDeploy").Error(err, "Agentparser Deployment YAML Unmarshal to JSON failed")
			//}

			depObj, err := YamlUnmarshalHandle(depBytes, dep, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
				return nil, err
			}

			dep = depObj.(*appsv1.Deployment)
			dep.Spec.Template.Spec.Containers[0].Env = level3ContainerEnv
			dep.Spec.Template.Spec.Containers[0].Resources = resourceLimitLevel

			svc := &corev1.Service{}
			//err = yaml.Unmarshal(svcBytes, svc)
			//if err != nil {
			//	logger.WithName("Installer NewDeploy").Error(err, "Agentparser Service YAML Unmarshal to JSON failed")
			//}
			//logger.WithName("Installer NewDeploy").Info("Unmarshal Agentparser and Service YAML to Resource Type success")

			svcObj, err := YamlUnmarshalHandle(svcBytes, svc, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
				return nil, err
			}

			svc = svcObj.(*corev1.Service)
			if v.EnableNodePort == true {
				logger.WithName("Installer NewDeploy" + k).Info(" Service enabled http Port")
				svc.Spec.Type = "NodePort"
				svc.Spec.Ports[0].NodePort = v.NodePort
			}

			if v.EnableConfigmap {
				cm := &corev1.ConfigMap{}
				cmName := strings.TrimSuffix(k, "-java")
				if _, ok := installer.Spec.Configmaps[cmName]; ok {
					cm.Data = installer.Spec.Configmaps[cmName]
				} else {
					// Template Parse and rendered Configmap YAML file
					configmapBytes, err := TemplateParseHandle(files.AppConfigmapYaml, config, k, logger)
					if err != nil {
						logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Configmap YAML file failed")
						return nil, err
					}
					logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(" Template Execute Configmap YAML file success")

					cmObj, err := YamlUnmarshalHandle(configmapBytes, cm, logger)
					if err != nil {
						logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
						return nil, err
					}
					cm = cmObj.(*corev1.ConfigMap)
					cm.Name = cmName
					cm.Data = installer.Spec.Configmaps[cmName]
					resources = append(resources, cm)
				}

			}

			resources = append(resources, dep, svc)

		default:
			logger.WithName("Installer NewDeploy " + k).Info("Handle Deployment " + k)
			// 定义变量
			config := Config{
				Name:          k,
				Image:         v.Image,
				InitImage:     installer.Spec.InitImage,
				Port:          appsPort,
				Namespace:     installer.Namespace,
				ConfigmapName: k,
			}

			// 解析模板
			//depTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/redis.yaml")
			//tmpl, err := template.New("yaml").Parse("/data/operator/installer/internal/files/redis.yaml")

			logger.WithName("Installer NewDeploy " + k).Info("Handle template YAML file " + k)

			// Template Parse and rendered Deployment YAML file
			depBytes, err := TemplateParseHandle(files.AppsYaml, config, k, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
				return nil, err
			}
			logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

			//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")

			// Unmarshal Deployment Bytes to appsv1.Deployment type
			dep := &appsv1.Deployment{}
			depObj, err := YamlUnmarshalHandle(depBytes, dep, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
				return nil, err
			}
			dep = depObj.(*appsv1.Deployment)
			dep.Spec.Template.Spec.Containers[0].Env = level3ContainerEnv
			dep.Spec.Template.Spec.Containers[0].Resources = resourceLimitLevel

			// Template Parse and rendered Service YAML file
			svcBytes, err := TemplateParseHandle(files.AppServiceYaml, config, k, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
				return nil, err
			}
			logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

			svc := &corev1.Service{}
			svcObj, err := YamlUnmarshalHandle(svcBytes, svc, logger)
			if err != nil {
				logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
				return nil, err
			}
			svc = svcObj.(*corev1.Service)
			if v.EnableNodePort == true {
				logger.WithName("Installer NewDeploy").Info("Agentparser Service enabled http Port")
				svc.Spec.Type = "NodePort"
				svc.Spec.Ports[0].NodePort = v.NodePort
			}

			if v.EnableConfigmap {
				cm := &corev1.ConfigMap{}
				cmName := strings.TrimSuffix(k, "-java")
	
				if _, ok := installer.Spec.Configmaps[cmName]; !ok {
					logger.WithName("Installer Deploy Configmap "+k).Error(err, " Configmap is not found in the crd file!")
					return nil, err
				} else {
					// Template Parse and rendered Configmap YAML file
					configmapBytes, err := TemplateParseHandle(files.AppConfigmapYaml, config, k, logger)
					if err != nil {
						logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Configmap YAML file failed")
						return nil, err
					}
					logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(" Template Execute Configmap YAML file success")

					cmObj, err := YamlUnmarshalHandle(configmapBytes, cm, logger)
					if err != nil {
						logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
						return nil, err
					}
					cm = cmObj.(*corev1.ConfigMap)
					cm.Name = cmName
					cm.Data = installer.Spec.Configmaps[cmName]
					resources = append(resources, cm)
				}

			}

			resources = append(resources, dep, svc)
		}
	}

	for k, v := range installer.Spec.LecangAppsVue {

		// check resource limit
		var resourceLimitLevel corev1.ResourceRequirements
		switch v.LimitLevel {
		case 0:
			resourceLimitLevel = testResourceLimit
		case 1:
			resourceLimitLevel = level1ResourceLimit
		case 2:
			resourceLimitLevel = level2ResourceLimit
		case 3:
			resourceLimitLevel = level3ResourceLimit
		}

		logger.WithName("Installer NewDeploy " + k).Info("Handle Deployment " + k)
		// 定义变量
		config := Config{
			Name:      k,
			Image:     v.Image,
			Port:      appsPort,
			Namespace: installer.Namespace,
		}

		// 解析模板
		//depTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/redis.yaml")
		//tmpl, err := template.New("yaml").Parse("/data/operator/installer/internal/files/redis.yaml")

		logger.WithName("Installer NewDeploy " + k).Info("Handle template YAML file " + k)

		// Template Parse and rendered Deployment YAML file
		depBytes, err := TemplateParseHandle(files.AppsVueYaml, config, k, logger)
		if err != nil {
			logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
			return nil, err
		}
		logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

		//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")

		// Template Parse and rendered Service YAML file
		svcBytes, err := TemplateParseHandle(files.AppServiceYaml, config, k, logger)
		if err != nil {
			logger.WithName("Installer NewDeploy TemplateParseHandle "+k).Error(err, " Template Execute Service YAML file failed")
			return nil, err
		}
		logger.WithName("Installer NewDeploy TemplateParseHandle " + k).Info(k + " Template Execute Service YAML file success")

		// Unmarshal Deployment Bytes to appsv1.Deployment type
		dep := &appsv1.Deployment{}
		//err = yaml.Unmarshal(depBytes, dep)
		//if err != nil {
		//	logger.WithName("Installer NewDeploy").Error(err, "Agentparser Deployment YAML Unmarshal to JSON failed")
		//}

		depObj, err := YamlUnmarshalHandle(depBytes, dep, logger)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
			return nil, err
		}

		dep = depObj.(*appsv1.Deployment)
		dep.Spec.Template.Spec.Containers[0].Env = level3ContainerEnv
		dep.Spec.Template.Spec.Containers[0].Resources = resourceLimitLevel

		svc := &corev1.Service{}
		//err = yaml.Unmarshal(svcBytes, svc)
		//if err != nil {
		//	logger.WithName("Installer NewDeploy").Error(err, "Agentparser Service YAML Unmarshal to JSON failed")
		//}
		//logger.WithName("Installer NewDeploy").Info("Unmarshal Agentparser and Service YAML to Resource Type success")

		svcObj, err := YamlUnmarshalHandle(svcBytes, svc, logger)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+k).Error(err, " Deployment YAML Unmarshal to JSON failed")
			return nil, err
		}

		svc = svcObj.(*corev1.Service)
		if v.EnableNodePort == true {
			logger.WithName("Installer NewDeploy" + k).Info(" Service enabled http Port")
			svc.Spec.Type = "NodePort"
			svc.Spec.Ports[0].NodePort = v.NodePort
		}

		resources = append(resources, dep, svc)

	}

	return resources, nil
}

func TemplateParseHandle(resourceYaml []byte, config Config, resourceName string, logger logr.Logger) ([]byte, error) {

	//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")
	resTmpl, err := template.New("yaml").Parse(string(resourceYaml))
	if err != nil {
		logger.WithName("Installer NewDeploy TemplateParse "+resourceName).Error(err, " Template parse Service YAML file failed!")
		return nil, err
	}
	logger.WithName("Installer NewDeploy TemplateParse " + resourceName).Info(" Template parse Service YAML file success")

	// 将变量注入模板并渲染
	resbuf := new(bytes.Buffer)
	err = resTmpl.Execute(resbuf, config)
	resBytes := resbuf.Bytes()
	//err = tmpl.Execute(os.Stdout, config)
	if err != nil {
		logger.WithName("Installer NewDeploy "+resourceName).Error(err, " Template Execute Service YAML file failed!")
		return nil, err
	}

	logger.WithName("Installer NewDeploy " + resourceName).Info("Template Execute Service YAML file success")

	return resBytes, nil
}

func YamlUnmarshalHandle(resourceBytes []byte, object v1.Object, logger logr.Logger) (v1.Object, error) {
	switch res := object.(type) {
	case *corev1.Service:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil

	case *appsv1.Deployment:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *corev1.ConfigMap:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *corev1.ServiceAccount:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *rbacv1.ClusterRoleBinding:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *rbacv1.ClusterRole:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *rbacv1.Role:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *rbacv1.RoleBinding:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *storagev1.StorageClass:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer StorageClass yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	case *corev1.PersistentVolumeClaim:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer PVC yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil

	case *corev1.PersistentVolume:
		err := yaml.Unmarshal(resourceBytes, res)
		if err != nil {
			logger.WithName("Installer PV yamlUnmarshalHandle "+res.Name).Error(err, " YAML Unmarshal to JSON failed")
			return nil, err
		}
		return res, nil
	default:
		logger.WithName("Installer NewDeploy yamlUnmarshalHandle ").Error(errors.New("unsupported Type"), "No the resource type...")
		return nil, errors.New("unsupported Type")
	}

}

func handleMiddlewares(config Config, resName string, info v1beta1.MiddleInfo, logger logr.Logger,
	resLimit corev1.ResourceRequirements) (dep *appsv1.Deployment, svc *corev1.Service, err error) {
	var depBytes, svcBytes, fileBytes []byte

	logger.WithName("Installer NewDeploy").Info("Handle Deployment Rabbitmq...")

	// 解析模板
	//depTmpl, err := template.ParseFiles("internal/files/rabbitmq.yaml")
	logger.WithName("Installer NewDeploy").Info("template parse Yaml Rabbitmq...")

	// Template Parse and rendered Deployment YAML file
	switch resName {
	case "rabbitmq":
		fileBytes = files.RabbitmqYaml
	case "redis":
		fileBytes = files.RedisYaml
	case "minio":
		fileBytes = files.MinioYaml
	case "nginx":
		//fileBytes = files.nginxYaml
		logger.WithName("Operator Installer ").Info("Handle Nginx TODO...")
	default:
		logger.WithName("hanleMiddlewares "+resName).Error(err, " The resource do not exist! ")
		return nil, nil, fmt.Errorf("hanleMiddlewares %s ERROR,The resource do not exist, %v", resName, err)
	}

	depBytes, err = TemplateParseHandle(fileBytes, config, resName, logger)
	if err != nil {
		logger.WithName("Installer NewDeploy TemplateParseHandle "+resName).Error(err, " Template Execute Deployment YAML file failed")
		return nil, nil, err
	}
	logger.WithName("Installer NewDeploy TemplateParseHandle " + resName).Info(" Template Execute Deployment YAML file success")

	dep = &appsv1.Deployment{}
	depObj, err := YamlUnmarshalHandle(depBytes, dep, logger)
	if err != nil {
		logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+resName).Error(err, " Deployment YAML Unmarshal to JSON failed")
		return nil, nil, err
	}
	dep = depObj.(*appsv1.Deployment)
	dep.Spec.Template.Spec.Containers[0].Resources = resLimit

	//svcTmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")

	// Template Parse and rendered Service YAML file
	svcBytes, err = TemplateParseHandle(files.ServiceYaml, config, resName, logger)
	if err != nil {
		logger.WithName("Installer NewDeploy TemplateParseHandle "+resName).Error(err, " Template Execute Service YAML file failed")
		return nil, nil, err
	}
	logger.WithName("Installer NewDeploy TemplateParseHandle " + resName).Info(resName + " Template Execute Service YAML file success")

	svc = &corev1.Service{}
	svcObj, err := YamlUnmarshalHandle(svcBytes, svc, logger)
	if err != nil {
		logger.WithName("Installer NewDeploy yamlUnmarshalHandle "+resName).Error(err, " Deployment YAML Unmarshal to JSON failed")
		return nil, nil, err
	}
	svc = svcObj.(*corev1.Service)

	logger.WithName("Installer NewDeploy " + resName).Info("Unmarshal Deployment and Service Yaml to Resource Type success")
	if info.EnableHttpPort {
		logger.WithName("Installer NewDeploy " + resName).Info("Service enabled http Port")
		svc.Spec.Type = "NodePort"
		httpPort := corev1.ServicePort{
			Name:     "http",
			Protocol: corev1.ProtocolTCP,
			Port:     int32(info.HttpPort),
			TargetPort: intstr.IntOrString{
				IntVal: int32(info.HttpPort),
			},
			NodePort: int32(info.HttpNodePort),
		}
		svc.Spec.Ports = append(svc.Spec.Ports, httpPort)
	}
	return dep, svc, nil
}

func TemplateParsePv(resName, pvName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		PvName:             pvName,
		StorageSize:        installer.Spec.Storage.StorageSize,
		PvLocalPath:        installer.Spec.Storage.PvLocalPath,
		PvNodeName:         installer.Spec.Storage.PvNodeName,
		PvStorageClassName: installer.Spec.Storage.PvStorageClassName,
	}
	return TemplateParseHandle(files.PvYaml, config, resName, logger)
}
func TemplateParsePvc(resName, PvcName string, logger logr.Logger, installer *v1beta1.Installer) ([]byte, error) {
	config := Config{
		PvcName:             PvcName,
		Namespace:           installer.Namespace,
		PvcStorageClassName: installer.Spec.Storage.PvcStorageClassName,
		StorageSize:         installer.Spec.NfsProvisioner.StorageSize,
	}
	return TemplateParseHandle(files.PvcYaml, config, resName, logger)
}

//func NewService(installer *v1beta1.Installer) (resources []interface{}, err error) {
//	for _, v := range installer.Spec.Middlewares {
//		switch v.Name {
//		case "redis":
//			// 定义变量
//			config := Config{
//				Name:      v.Name,
//				Namespace: installer.Spec.NamespaceName,
//				Port:      v.Port,
//				NodePort:  v.NodePort,
//			}
//
//			fmt.Println("exec pwd command: ")
//			cmd := exec.Command("pwd")
//			// 执行命令，并捕获输出
//			output, err := cmd.Output()
//			if err != nil {
//				log.Fatal(err)
//			}
//
//			// 输出命令执行结果
//			fmt.Println(string(output))
//			// 解析模板
//			tmpl, err := template.ParseFiles("/data/operator/installer/internal/files/service.yaml")
//
//			// 将变量注入模板并渲染
//			b := new(bytes.Buffer)
//			err = tmpl.Execute(b, config)
//			i := b.Bytes()
//			//err = tmpl.Execute(os.Stdout, config)
//			if err != nil {
//				fmt.Println("Error executing template:", err)
//				os.Exit(1)
//			}
//			if err != nil {
//				fmt.Println("Error parsing template:", err)
//				os.Exit(1)
//			}
//
//			fmt.Println("======= deploy redis service")
//			d := &corev1.Service{}
//			err = yaml.Unmarshal(i, d)
//			if err != nil {
//				panic(err)
//			}
//			resources = append(resources, d)
//		}
//	}
//	return resources, nil
//}
